#!/usr/bin/python3

import re
import sys

pointers = {
    'prethink'  : 'void {p}(edict_t *)',
    'think'     : 'void {p}(edict_t *)',
    'blocked'   : 'void {p}(edict_t *, edict_t *)',
    'touch'     : 'void {p}(edict_t *, edict_t *, cplane_t *, csurface_t *)',
    'use'       : 'void {p}(edict_t *, edict_t *, edict_t *)',
    'pain'      : 'void {p}(edict_t *, edict_t *, float, int)',
    'die'       : 'void {p}(edict_t *, edict_t *, edict_t *, int, vec3_t)',
    'moveinfo_endfunc'          : 'void {p}(edict_t *)',
    'monsterinfo_currentmove'   : 'const mmove_t {p}',
    'monsterinfo_stand'         : 'void {p}(edict_t *)',
    'monsterinfo_idle'          : 'void {p}(edict_t *)',
    'monsterinfo_search'        : 'void {p}(edict_t *)',
    'monsterinfo_walk'          : 'void {p}(edict_t *)',
    'monsterinfo_run'           : 'void {p}(edict_t *)',
    'monsterinfo_dodge'         : 'void {p}(edict_t *, edict_t *, float)',
    'monsterinfo_attack'        : 'void {p}(edict_t *)',
    'monsterinfo_melee'         : 'void {p}(edict_t *)',
    'monsterinfo_sight'         : 'void {p}(edict_t *, edict_t *)',
    'monsterinfo_checkattack'   : 'bool {p}(edict_t *)',
}

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print('Usage: genptr.py <file> [...]')
        sys.exit(1)

    exprs = '|'.join(p.replace('_', '\\.') for p in pointers.keys() if not p == 'moveinfo_endfunc')
    regex = re.compile(r'->\s*(%s)\s*=\s*&?\s*(\w+)' % exprs, re.ASCII)
    regex2 = re.compile(r'\b(?:Angle)?Move_Calc\s*\(.+,\s*(\w+)\s*\)', re.ASCII)

    types = {}
    for p in pointers.keys():
        types[p] = []

    for a in sys.argv[1:]:
        with open(a) as f:
            for line in f:
                if not line.lstrip().startswith('//'):
                    match = regex.search(line)
                    if match:
                        t = types[match[1].replace('.', '_')]
                        p = match[2]
                        if not p in t and p != 'NULL':
                            t.append(p)
                        continue

                    match = regex2.search(line)
                    if match:
                        t = types['moveinfo_endfunc']
                        p = match[1]
                        if not p in t:
                            t.append(p)


    print('// generated by genptr.py, do not modify')
    print('#include "g_local.h"')
    print('#include "g_ptrs.h"')

    decls = []
    for k, v in types.items():
        for p in v:
            decls.append('extern ' + pointers[k].replace('{p}', p) + ';')
    for d in sorted(decls, key=str.lower):
        print(d)

    print('const save_ptr_t save_ptrs[] = {')
    for k, v in types.items():
        for p in sorted(v, key=str.lower):
            amp = '&' if k == 'monsterinfo_currentmove' else ''
            print('{ %s, %s%s },' % ('P_' + k, amp, p))
    print('};')
    print('const int num_save_ptrs = sizeof(save_ptrs) / sizeof(save_ptrs[0]);')
